#include "thread.h"
#include <exception>
#include <stdexcept>
#include <sstream>
Thread_notifyer dumynotifer{nullptr, nullptr};

ThreadFactory::ThreadFactory()
{
}

ThreadFactory *ThreadFactory::pins = new ThreadFactory();

std::shared_ptr<ThreadInterface> ThreadFactory::CreatThread(int type, int id, ThreadNotifyer note)
{
    return std::make_shared<Thread>(id, note);
}

ThreadFactory *ThreadFactory::GetInstance()
{
    return pins;
}

ThreadFactory::~ThreadFactory()
{
}

ThreadInterface::ThreadInterface(int id, ThreadNotifyer note) : id_(id), notifyer_(note), runflag_(THREAD_UNINIT)
{
}

ThreadInterface::~ThreadInterface()
{
}

int Thread::Start()
{
    if (runflag_.load() > THREAD_UNINIT)
    {
        //已经初始化过了
        return 0;
    }
    try
    {
        runflag_.store(THREAD_INITING);
        pointer2stdthread_.reset(new std::thread(&Thread::threadfunc, this));
        runflag_.store(THREAD_RUN);
    }
    catch (const std::exception &e)
    {
    }
    return 0;
}

int Thread::Stop()
{
    if (runflag_.load() != THREAD_RUN)
    {
        return -1;
    }
    try
    {
        runflag_.store(THREAD_STOPPING);
        signalcond_.notify_all();
        pointer2stdthread_->join();
        pointer2stdthread_.reset(nullptr);
        runflag_.store(THREAD_STOPPED);
    }
    catch (const std::exception &e)
    {
    }
    return 0;
}

Thread::Thread(const int id, ThreadNotifyer pNotify) : ThreadInterface(id, pNotify),
                                                       pointer2stdthread_(nullptr),
                                                       customfunction_(nullptr),
                                                       customargs_(nullptr)
{
}

Thread::~Thread()
{
}

int Thread::Post(FuncType func, std::shared_ptr<void> args)
{
    if (customfunction_ == nullptr)
    {
        std::unique_lock<std::mutex> ulock(signalmutex_);
        customfunction_ = func;
        customargs_ = args;
    }
    signalcond_.notify_one();
    return 0;
}

int Thread::threadfunc()
{
    while (runflag_.load() != THREAD_STOPPING)
    {
        FuncType tempFunc = nullptr;
        std::shared_ptr<void> tempargs(nullptr);
        {
            std::unique_lock<std::mutex> ulock(signalmutex_);
            signalcond_.wait(ulock, [&tempargs, &tempFunc, this]
                            {
                                if(runflag_.load() == THREAD_STOPPING)
                                {
                                    //被唤醒是要退出线程
                                    tempFunc = nullptr;
                                    return true;
                                }
                                //被唤醒是因为有工作
                                if(customfunction_!=nullptr)
                                {
                                    tempFunc = customfunction_;
                                    tempargs = customargs_;
                                    customfunction_ = nullptr;
                                    customargs_.reset();
                                    return true;
                                }
                                else
                                {   
                                    //假醒
                                    return false;
                                } 
                            }
                            );
        }
        if (tempFunc != nullptr)
        {
            if (notifyer_->pstart != nullptr)
            {
                notifyer_->pstart(id_, 1);
            }
            try
            {
                tempFunc(tempargs);    
            }
            catch(const std::exception& e){}
            if (notifyer_->pstop != nullptr)
            {
                notifyer_->pstop(id_, 2);
            }
        }
    }
    return 0;
}